package com.gitee.wsl.ext.string

import com.gitee.wsl.ext.compile
import com.gitee.wsl.text.predicate.CharMatcher


private val HEX_CHARS = CharMatcher.anyOf("0123456789abcdefABCDEF").precomputed()

fun String.isNoPrefixHex(): Boolean {
    return HEX_CHARS.matchesAllOf(this)
}

/*
     * Regex to accurately remove _at most two_ '=' characters from the end of the input.
     */
private val BASE64_PATTERN = Regex.compile("==?$")

/*
     * Negation of the Base64 alphabet. We try and find one character, if any, matching this "negated" character
     * matcher.
     *
     * FIXME: use .precomputed()?
     */
private val NOT_BASE64: CharMatcher = CharMatcher.inRange('a', 'z').or(CharMatcher.inRange('A', 'Z'))
    .or(CharMatcher.inRange('0', '9')).or(CharMatcher.anyOf("+/")).negate()


fun String.isBase64(): Boolean {
    /*
     * The string length must be a multiple of 4. FIXME though: can it be 0? Here, it is assumed that it can, even
     * though that does not really make sense.
     */
    if (length % 4 != 0) {
        return false
    }

    val index = NOT_BASE64.indexIn(BASE64_PATTERN.replaceFirst(this,""))

    return index == -1
}

fun String.isMD5(): Boolean {
    return isNoPrefixHex() && length == 32
}

fun String.isSha1(): Boolean {
    return isNoPrefixHex() && length == 40
}

fun String.isSha256(): Boolean {
    return isNoPrefixHex() && length == 64
}

fun String.isSha512(): Boolean {
    return isNoPrefixHex() && length == 128
}